#include <blackbox/blackbox.h>

#ifdef BUOLA_HAVE_PULSE

#include "cpulsecontext.h"
#include "cpulseloop.h"

namespace buola { namespace media { namespace pulse {

static void context_state_callback(pa_context *pC,void *pPC)
{
    CPulseContext *lPC=reinterpret_cast<CPulseContext*>(pPC);

    lPC->GetLoop().Signal();
}

CPulseContext::CPulseContext(CPulseLoop &pLoop,const std::string &pName)
    :   mLoop(pLoop)
{
    CPulseLock lLock(mLoop);
    mCtx=pa_context_new(pa_threaded_mainloop_get_api(pLoop.mLoop),pName.c_str());
    pa_context_set_state_callback(mCtx,context_state_callback,this);
}

CPulseContext::~CPulseContext()
{
    CPulseLock lLock(mLoop);
    pa_context_disconnect(mCtx);
    pa_context_unref(mCtx);
}

void CPulseContext::Connect()
{
    CPulseLock lLock(mLoop);
    pa_context_connect(mCtx,nullptr,PA_CONTEXT_NOFLAGS,nullptr);
}

void CPulseContext::Connect(const std::string &pServer)
{
    CPulseLock lLock(mLoop);
    pa_context_connect(mCtx,pServer.c_str(),PA_CONTEXT_NOFLAGS,nullptr);
}

bool CPulseContext::WaitForConnection()
{
    CPulseLock lLock(mLoop);
    while(true)
    {
        pa_context_state_t lState=pa_context_get_state(mCtx);

        if(lState==PA_CONTEXT_READY)
            return true;
        else if(lState==PA_CONTEXT_FAILED||lState==PA_CONTEXT_TERMINATED)
            return false;

        mLoop.Wait();
    }
}

/*namespace pulse*/ } /*namespace media*/ } /*namespace buola*/ }

#endif //BUOLA_HAVE_PULSE
